package spring.xmlParser.parserImplementations;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import spring.beanDefinition.BeanDefinition;
import spring.beanDefinition.PropertyEntry;
import spring.beanDefinition.Value;
import spring.beanDefinition.ValueType;
import spring.xmlParser.XmlParser;

@SuppressWarnings("restriction")
public class StAXParser implements XmlParser{

	@Override
	public Map<String, BeanDefinition> parse(String filePath)
			throws FileNotFoundException, XMLStreamException{
		
		XMLInputFactory factory = XMLInputFactory.newFactory();
		XMLStreamReader reader =
                factory.createXMLStreamReader(new FileInputStream(new File(filePath)));
		
		Map<String, BeanDefinition> result = null;
		BeanDefinition beanDefinition = null;
		
		while(reader.hasNext()){
			int event = reader.next();
			
			switch (event){
				case XMLStreamConstants.START_ELEMENT:
					switch (reader.getLocalName()){
						case "beans":{
							result = new HashMap<String, BeanDefinition>();
							break;
						}
						case "bean": {
							beanDefinition = new BeanDefinition();
							beanDefinition.id = reader.getAttributeValue(0);
							beanDefinition.clazz = reader.getAttributeValue(1);
							break;
						}
		                case "constructor-arg": {
		                	Value argValue = new Value();
		                	argValue.value = reader.getAttributeValue(0);
		                	if(reader.getAttributeName(0).toString().equals("value")){
		                		argValue.type = ValueType.VALUE;
		                	}
		                	else if(reader.getAttributeName(0).toString().equals("ref")){
		                		argValue.type = ValueType.REF;
		                	}
		                	beanDefinition.constructorArgs.add(argValue);
		                	break;
		                }
		                case "property": {
		                	PropertyEntry propertyEntry = new PropertyEntry();
		                	Value argValue = new Value();
		                	propertyEntry.name = reader.getAttributeValue(0);
		                	argValue.value = reader.getAttributeValue(1);
		                	if(reader.getAttributeName(1).toString().equals("value")){
		                		argValue.type = ValueType.VALUE;
		                	}
		                	else if(reader.getAttributeName(1).toString().equals("ref")){
		                		argValue.type = ValueType.REF;
		                	}
		                	propertyEntry.value = argValue;
		                	beanDefinition.properties.add(propertyEntry);
		                }
					}
					break;
					
				case XMLStreamConstants.END_ELEMENT:
                    switch (reader.getLocalName()){
                        case "bean":
                        	result.put(new String(beanDefinition.id), beanDefinition);
                        	break;

                    }
                    break;
			}
		}
		return result;
	}

}
